作者: diseac / 版本: 0.1.4 / 使用环境: Avisynth 2.5.x, YV12/YUY2
发布地址: http://www.nmm-hd.org/bbs/thread-667-1-1.html (nmm论坛)
AAD (int "mode", bool "tff", string "ovr", bool "debug", bool "ivtc2pass", bool "ivtc3pass", bool "finalpass", bool "ultimate", bool "top2px")
AADTrim (int "stf", int "edf", string "func", string "func2", clip "clip1", clip "clip2")
关于AADivtc,理论上说它是我的原创算法。因为首先它是我自己想出来的,其次我没有见过别人这样操作过。但实际上也是借助了 IsCombedTIVTC() 和 tdecimate() 这两个外部插件所提供的函数才实现的,所以不能算是完全意义上的原创吧。
AADivtc服务于AAD(mode=2),虽然我创建了独立函数,但是请不要独立使用它。它的算法很简单,但如果运气好的话,它可以达到100%的正确匹配,而且不会出现jerk现象。但这只是最理想的情况,在实际操作中,它基本只能保持60%以上的正确率。
在avisynth里我没有办法使用更高级的算法,所以 AADivtc现在还很简单,但有时候它可能会更完美地解决一些顽固拉丝。
当设置mode=2时,将由AADivtc()执行1st pass,2nd pass将被强制关闭,ovr也不再生效,但 3rd pass 与 4th pass 仍然可以进行。
请注意,如果你这样设置:AAD(mode=2,ivtc3pass=false,finalpass=false),这完全等同于AADivtc()裸奔,我极力不推荐你这样做。也许你观察mode=2处理出的影片时不会发现它有什么错误,但我建议你不要对整片使用mode=2选项。mode=2的设计旨在与mode=1互补,如果你使用mode=1时发现有某一小段令你不满意,你可以试试mode=2,如果你觉得它更好,你可以用该部分的帧替换你不满意的帧。
内置函数AADTrim可以轻松做到这点,下面一段脚本说明了如何简单地将mode=1处理出的第10-20帧、及30-40帧替换为mode=2所处理的。
mode2 = last.AAD(mode=2)
AAD(mode=1).AADTrim(10,20,clip1=mode2).AADTrim(30,40,clip1=mode2)
AAD()
AAD(top2px=true)
AAD(mode=0)
AAD(ovr="x:\xx\xx.txt")
AAD(debug=true)
AADTrim(100,200,"warpsharp()","UnsharpMask()")
c1=last.TurnLeft
c2=last.TurnRight
AADTrim(100,200,clip1=c1,clip2=c2)
function AAD (
\ clip v, int "mode", bool "tff", string "ovr", bool "debug",
\ bool "ivtc2pass", bool "ivtc3pass", bool "finalpass", bool "ultimate",
\ bool "top2px" )
{
mode = default(mode,1)
tff = default(tff,true)
ovr = default(ovr,"noovr")
debug = default(debug,false)
ivtc2pass = default(ivtc2pass,true)
ivtc3pass = default(ivtc3pass,true)
finalpass = default(finalpass,true)
ultimate = default(ultimate,false)
top2px = default(top2px ,false)
last =
\ mode == 0 ? AADmode0(v,"tfm_log.txt")
\ : mode == 1 ? AADmode1(v,mode,tff,ovr,debug,ivtc2pass,ivtc3pass,finalpass,ultimate,top2px)
\ : mode == 2 ? AADmode1(v,mode,tff,ovr,debug,ivtc2pass,ivtc3pass,finalpass,ultimate,top2px)
\ : blankclip(pixel_type="YV12").subtitle("AAD Error: mode="+string(mode)+" is not correct parameter")
return(last)
}
# AAD mode 0: Output tfm's log
function AADmode0 (clip v, string "output"){
last = v.tfm(mode=3,slow=2,pp=1,output=output,debug=true,display=true)
return(last)
}
# AAD mode 1: 30i->24p 4passes IVTC
# AAD mode 2: 30i->24p 3passes IVTC with AAD original IVTC arithmetic
function AADmode1 (
\ clip v, int "mode", bool "tff", string "ovr", bool "debug",
\ bool "ivtc2pass", bool "ivtc3pass", bool "finalpass", bool "ultimate",
\ bool "top2px" ){
vy = v.height
finalpass = ultimate && ivtc3pass ? false : finalpass
last = v
mode==1
\ ? AADdebug(debug,120,"AAD mode 1: 4passes IVTC")
\ : AADdebug(debug,120,"AAD mode 2: Another way IVTC")
vp11 = tff
\ ? DoubleWeave.a60224().AssumeTFF
\ : DoubleWeave.a60224().AssumeBFF
vp12 = ovr=="noovr"
\ ? tfm(mode=3,slow=2,pp=0,debug=debug,display=debug).tdecimate(mode=1)
\ : tfm(mode=3,slow=2,pp=0,debug=debug,display=debug,ovr=ovr).tdecimate(mode=1)
vp2 = ovr=="noovr"
\ ? conditionalfilter(vp11,
\ vp12.AADdebug(debug,150,"1pass - a60224 [drop]").AADdebug(debug,170,"2pass - tfm [on]"),
\ vp11.AADdebug(debug,150,"1pass - a60224 [on]").AADdebug(debug,170,"2pass - tfm [drop]"),
\ "IsCombedTIVTC","==","true")
\ : conditionalfilter(vp12,
\ vp11.AADdebug(debug,150,"1pass - tfm [drop]").AADdebug(debug,170,"2pass - a60224 [on]"),
\ vp12.AADdebug(debug,150,"1pass - tfm [on]").AADdebug(debug,170,"2pass - a60224 [drop]"),
\ "IsCombedTIVTC","==","true")
mode==1
\ ? ivtc2pass
\ ? vp2
\ : ovr=="noovr"
\ ? vp11.AADdebug(debug,150,"1pass - a60224 [on]").AADdebug(debug,170,"2pass [off]")
\ : vp12.AADdebug(debug,150,"1pass - tfm [on]").AADdebug(debug,170,"2pass [off]")
\ : AADivtc(tff).AADdebug(debug,150,"1pass - AADivtc [on]").AADdebug(debug,170,"2pass [forced off]")
vp31 = TDeint(mode=2,slow=2,full=false,mtnmode=3,tryweave=true,emask=tmm(1),
\ edeint=separatefields().eedi2(field=-2,nt=128))
\ .AADdebug(debug,190,"3pass [limit]")
vp32 = TDeint(mode=2,slow=2,full=false,mtnmode=3,tryweave=true,emask=tmm(1),
\ edeint=StackVertical(crop(0,2,0,0),crop(0,2,0,0)).separatefields().
\ eedi2(field=-2,nt=128).crop(0,0,0,vy-2).addborders(0,2,0,0))
\ .AADdebug(debug,190,"3pass [limit]")
vp33 = TDeint(mode=2,slow=2,mthreshL=0,mthreshC=0,
\ edeint=separatefields().eedi2(field=-2,nt=128))
\ .AADdebug(debug,190,"3pass [ultimate]")
vp34 = TDeint(mode=2,slow=2,mthreshL=0,mthreshC=0,
\ edeint=StackVertical(crop(0,2,0,0),crop(0,2,0,0)).separatefields().
\ eedi2(field=-2,nt=128).crop(0,0,0,vy-2).addborders(0,2,0,0))
\ .AADdebug(debug,190,"3pass [ultimate]")
ivtc3pass ? ultimate ? top2px ? vp34 : vp33 : top2px ? vp32 : vp31 : AADdebug(debug,190,"3pass [off]")
vp41 = Vinverse().AADdebug(debug,210,"4pass [on]")
vp42 = crop(0,2,0,0).Vinverse().addborders(0,2,0,0).AADdebug(debug,210,"4pass [on]")
finalpass ? top2px ? vp42 : vp41 : AADdebug(debug,210,"4pass [off]")
top2px ? AADdebug(debug,240,"top2px [on]") : AADdebug(debug,240,"top2px [off]")
ovr=="noovr" ? AADdebug(debug,260,"tfm's ovr [off]") : AADdebug(debug,260,"tfm's ovr [on]")
return(last)
}
# AAD original IVTC arithmetic
function AADivtc (clip v, bool "tff"){
tff=default(tff,true)
v1=v.DoubleWeave.selecteven
v2=v.DoubleWeave.selectodd
conditionalfilter(v1,v2,v1,"IsCombedTIVTC","==","true")
tff ? assumeTFF : assumeBFF
tdecimate(mode=1)
return(last)
}
# AAD debug function: for display debug infomation on screen
function AADdebug (clip v, bool "debug", int "y", string "showinfo"){
last=v
debug ? subtitle(showinfo,y=y) : nop
return(last)
}
# Trim cilp and use some other functions or second clip
function AADTrim(clip v, int "stf", int "edf", string "func", string "func2", clip "clip1", clip "clip2"){
eof = v.framecount-1
stf = stf<0 ? 0 : stf
edf = edf>eof ? eof : edf
edf = (edf==0)&&(stf>0) ? eof : edf
edf = edf<0 ? 0-edf+stf-1 : edf
edf = edf<stf ? stf : edf
vv = defined(clip2) ? clip2 : v
v = defined(clip1) ? clip1 : v
v1 =
\ defined(func2)
\ ? (stf==1)
\ ? eval("vv.trim(0,-1)."+func2)
\ : eval("vv.trim(0,stf-1)."+func2)
\ : (stf==1)
\ ? vv.trim(0,-1)
\ : vv.trim(0,stf-1)
v2 =
\ defined(func)
\ ? (stf==0)&&(edf==0)
\ ? eval("v.trim(0,-1)."+func)
\ : eval("v.trim(stf,edf)."+func)
\ : (stf==0)&&(edf==0)
\ ? v.trim(0,-1)
\ : v.trim(stf,edf)
v3 =
\ defined(func2)
\ ? eval("vv.trim(edf+1,eof)."+func2)
\ : vv.trim(edf+1,eof)
last=
\ stf==0 ? v2+v3 :
\ edf==eof ? v1+v2 :
\ v1+v2+v3
defined(clip2) ? (clip2.framecount-1==eof) ? nop :
\ blankclip(pixel_type="YV12").subtitle("AADTrim Error: clip2's framecount must be same as last clip") : nop
last.framecount-1==eof ? nop :
\ blankclip(pixel_type="YV12").subtitle("AADTrim Error: framecount doesn't match")
return(last)
}